﻿using System;
using System.Diagnostics;
using System.Threading;
using AzureStorageMapper.TableStorage;
using AzureStorageMapper.TableStorage.ActionModes;
using AzureStorageMapper.TableStorage.Attributes;
using AzureStorageMapper.TableStorage.RESTCommunicate;
using AzureStorageMapper.TableStorage.Utils;
using NUnit.Framework;

namespace AzureStorageMapper.Tests.TableStorage.RESTCommunicate
{
    [TestFixture]
    public class TalkToTableStorage_CURDTests
    {
        private TalkToTableStorage _talkToTableStorage;

        [SetUp]
        public void SetupTest()
        {
            _talkToTableStorage = new TalkToTableStorage(AccountInfo.TableStorageAccountName, AccountInfo.TableStorageAccountKey);
            
            TableInfo tInfo = TableUtilities.GetTableInfo(typeof(SampleTableModel));
            Trace.TraceInformation("Creating table '{0}' ...", tInfo.Name);
            _talkToTableStorage.CreateTable(tInfo);

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));
        }

        [TearDown]
        public void TearDownTest()
        {
            TableInfo tInfo = TableUtilities.GetTableInfo(typeof(SampleTableModel));

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));

            Trace.TraceInformation("Deleting table '{0}' ...", tInfo.Name);
            _talkToTableStorage.DeleteTable(tInfo);
        }


        [Test]
        public void EntryCURD_Test()
        {
            SampleTableModel stm = new SampleTableModel("Default", Guid.NewGuid().ToString());
            stm.ColumnOne = "I am col 1";
            stm.ColumnTwo = 2;
            stm.ColumnThree = 3L;
            stm.ColumnFour = DateTime.Now;
            stm.ColumnFive = 12.34;
            stm.ColumnSix = null;
            stm.ColumnSeven = string.Empty;
            stm.ColumnEight = System.Text.Encoding.UTF8.GetBytes("Helllo world");

            EntityInfo eInfo = TableUtilities.GetEntityInfo(stm);

            Trace.TraceInformation("Inserting entry into '{0}'", eInfo.TableName);
            _talkToTableStorage.InsertEntity(eInfo, SaveMode.Insert);

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));

            SampleTableModel stm2 = _talkToTableStorage.QueryEntity<SampleTableModel>("SampleTable", stm.PartitionKey, stm.RowKey);

            Trace.TraceInformation("Comparing ...");
            Assert.AreEqual(stm.PartitionKey, stm2.PartitionKey);
            Assert.AreEqual(stm.RowKey, stm2.RowKey);
            Assert.AreEqual(stm.ColumnOne, stm2.ColumnOne);
            Assert.AreEqual(stm.ColumnTwo, stm2.ColumnTwo);
            Assert.AreEqual(stm.ColumnThree, stm2.ColumnThree);
            Assert.AreEqual(stm.ColumnFour, stm2.ColumnFour);
            Assert.AreEqual(stm.ColumnFive, stm2.ColumnFive);
            Assert.AreEqual(stm.ColumnSix, stm2.ColumnSix);
            Assert.AreEqual(stm.ColumnSeven, stm2.ColumnSeven);
            Assert.AreEqual(stm.ColumnEight, stm2.ColumnEight);
            Trace.TraceInformation("All assertion passed after insert ... ");

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));

            Trace.TraceInformation("Updating two columns ...");
            stm2.ColumnOne = "I am updated col 1";
            stm2.ColumnEight = System.Text.Encoding.UTF8.GetBytes("Helllo world again !!!");
            EntityInfo eInfo2 = TableUtilities.GetEntityInfo(stm2);
            _talkToTableStorage.UpdateEntity(eInfo2, UpdateMode.Update);

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));

            SampleTableModel stm3 = _talkToTableStorage.QueryEntity<SampleTableModel>("SampleTable", stm.PartitionKey, stm.RowKey);

            Trace.TraceInformation("Comparing ...");
            Assert.AreEqual(stm3.PartitionKey, stm2.PartitionKey);
            Assert.AreEqual(stm3.RowKey, stm2.RowKey);
            Assert.AreEqual(stm3.ColumnOne, stm2.ColumnOne);
            Assert.AreEqual(stm3.ColumnTwo, stm2.ColumnTwo);
            Assert.AreEqual(stm3.ColumnThree, stm2.ColumnThree);
            Assert.AreEqual(stm3.ColumnFour, stm2.ColumnFour);
            Assert.AreEqual(stm3.ColumnFive, stm2.ColumnFive);
            Assert.AreEqual(stm3.ColumnSix, stm2.ColumnSix);
            Assert.AreEqual(stm3.ColumnSeven, stm2.ColumnSeven);
            Assert.AreEqual(stm3.ColumnEight, stm2.ColumnEight);
            Trace.TraceInformation("All assertion passed after update ... ");

            Trace.TraceInformation("Sleeping for 5 sec ...");
            Thread.Sleep(TimeSpan.FromSeconds(5));
            Trace.TraceInformation("Deleting entry from '{0}'", eInfo.TableName);
            _talkToTableStorage.DeleteEntity(eInfo.TableName, eInfo.PartitionKey, eInfo.RowKey);
        }

        [TableModel(Name = "SampleTable")]
        internal class SampleTableModel : TableEntity
        {
            [TableColumn]
            public string ColumnOne { get; set; }

            [TableColumn(Name = "Column2")]
            public int ColumnTwo { get; set; }

            [TableColumn]
            public long ColumnThree { get; set; }

            [TableColumn]
            public DateTime ColumnFour { get; set; }

            [TableColumn]
            public double ColumnFive { get; set; }

            [TableColumn]
            public string ColumnSix { get; set; }

            [TableColumn]
            public string ColumnSeven { get; set; }

            [TableColumn]
            public byte[] ColumnEight { get; set; }

            public SampleTableModel()
                : base(null, null)
            {
            }

            public SampleTableModel(string partitionKey, string rowKey)
                : base(partitionKey, rowKey)
            {
            }
        }
    }
}
